#ifndef STREAMHELPER_HEADER_FROM_CORE_INCLUDED
#define STREAMHELPER_HEADER_FROM_CORE_INCLUDED
////////////////////////////////////////////////////////////////////////////////
//	Copyright (c) 2004 by Michael 'Astar' Sotnikov
//	stari4ek at gmail dot com
////////////////////////////////////////////////////////////////////////////////

#include <ostream>
#include <vector>
#include <set>
#include <map>
#include <utility>

// helper for writing iterated-type (vector, list, etc.) to stream
template< typename OStream_t, typename Container_t >
OStream_t& WriteIterableToOStream( 	OStream_t& out, const Container_t& obj,
									const std::string& delimeter = ";" )
{
	// container must have const-iterator
	typedef typename Container_t::const_iterator ConstIter_t;
  	
	for( ConstIter_t cit = obj.begin(); cit != obj.end(); ++cit )
		out << ( *cit ) << delimeter;
		
	return out;	
} 

template< typename PairTy1_t, typename PairTy2_t, typename StreamTraits_t >
std::basic_ostream< char, StreamTraits_t >& operator << ( 	std::basic_ostream< char, StreamTraits_t >& out,
															const std::pair< PairTy1_t, PairTy2_t >& obj )
{
	out << obj.first << "|" << obj.second;
	return out;
}


// yeah, specialization of operator<< for all containers, cause i can't specialize
// it only for containers in-one-type. I've been failed with boost::enable_if  
template< typename VectorValue_t, typename StreamTraits_t >
std::basic_ostream< char, StreamTraits_t >&  operator << ( 	std::basic_ostream< char, StreamTraits_t >& out,
															const std::vector< VectorValue_t >& obj )
{
	return WriteIterableToOStream( out, obj );
}
	
template< typename SetKey_t, typename StreamTraits_t >
std::basic_ostream< char, StreamTraits_t >& operator << ( 	std::basic_ostream< char, StreamTraits_t >& out,
															const std::set< SetKey_t >& obj )
{
	WriteIterableToOStream( out, obj );
	return out;
}


template< typename MapKey_t, typename MapType_t, typename StreamTraits_t >
std::basic_ostream< char, StreamTraits_t >& operator << ( 	std::basic_ostream< char, StreamTraits_t >& out,
															const std::map< MapKey_t, MapType_t >& obj )
{
	WriteIterableToOStream( out, obj );
	return out;
}


#endif /* STREAMHELPER_HEADER_FROM_CORE_INCLUDED */
